#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "LockGuard.hpp"

using namespace std;

#define NUM 5
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class threadData
{
public:
    threadData(int number, pthread_mutex_t *mutex)
    {
        threadname = "thread-" + to_string(number);
        lock = mutex;
    }

public:
    string threadname;
    pthread_mutex_t *lock;
};

int tickets = 1000;

// void* getTicket(void* args)
// {
//     threadData* td = static_cast<threadData*>(args);
//     while(true)
//     {
//         pthread_mutex_lock(td->lock);
//         if(tickets > 0)
//         {
//             usleep(10000);
//             printf("who = %s, get a ticket: %d\n", td->threadname.c_str(), tickets);
//             tickets--;
//             pthread_mutex_unlock(td->lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->lock);
//             break;
//         }
//         usleep(15);
//     }
//     printf("%s ... quit\n", td->threadname.c_str());
//     return nullptr;
// }

void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    while (true)
    {
        {
            LockGuard lockguard(&lock);
            if (tickets > 0)
            {
                usleep(10000);
                printf("who = %s, get a ticket: %d\n", td->threadname.c_str(), tickets);
                tickets--;
            }
            else
            {
                break;
            }
        }
        usleep(15);
    }
    printf("%s ... quit\n", td->threadname.c_str());
    return nullptr;
}

int main()
{
    // pthread_mutex_t lock;
    // pthread_mutex_init(&lock, nullptr);

    vector<pthread_t> tids;
    vector<threadData *> thread_datas;
    for (int i = 1; i <= NUM; ++i)
    {
        pthread_t tid;
        threadData *td = new threadData(i, &lock);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, td);
        tids.push_back(tid);
    }

    for (int i = 0; i < tids.size(); ++i)
    {
        pthread_join(tids[i], nullptr);
    }
    for (int i = 0; i < thread_datas.size(); ++i)
    {
        delete thread_datas[i];
    }

    pthread_mutex_destroy(&lock);
}